package com.sunxd.zstudy.jvm.classload;

/**
 * 常用垃圾回收算法和策略
 *
 * 如何找到垃圾：
 *  · reference count引用计数 -循环引用解决不了
 *  · root searching 根可达算法

 *   对象指针
 * 常用垃圾回收算法
 *  · mark-sweep 标记清除 找到没用的清除 算法简单，存活对象比较多的情况效率比较高。两遍扫描，效率偏低，容易产生碎片 适合old区
 *  · copying 拷贝 适用于存活对象比较少的情况，只扫描一次，效率高没有碎片  适合eden区
 *  · mark-compact 标记压缩 不会产生碎片，方便对象对象分配，不会产生内存减半 扫描2次，需要移动对象
 *   三色标记法 黑色:自己遍历完及子节点也标记了，灰色：自己遍历完，子节点还没遍历。白色：未遍历。
 *           出现漏标：incremental update 增量更新
 *           SATB snapshot at the beginning -关注引用的删除 G1  使用
 *
 * 常见垃圾回收器：
 *  Serial（Y）（JDK诞生，单线程） 、Serial Old(Old)
 *      Serial 单线程(stop-the-wold)。找到一个安全的点所有的线程停止，清理垃圾，然后工作线程继续执行。停顿时间长
 *      Serial Old 单线程(stop-the-wold) 在老年代。找到一个安全的点所有的线程停止，清理垃圾，然后工作线程继续执行。停顿时间长
 *  Parallel Scavenge (Y)并行(多线程） 、 Parallel Old (Old)相比上面，只是清理的线程是多线程
 *      Parallel Scavenge 多线程(stop-the-wold)。找到一个安全的点所有的线程停止，清理垃圾，然后工作线程继续执行。停顿时间长
 *      Parallel Old 多线程(stop-the-wold) 在老年代。找到一个安全的点所有的线程停止，清理垃圾，然后工作线程继续执行。停顿时间长
 *  ParNew （Y）
 *      Parallel New (stop-the-wold) Parallel Scavenge的变种，配合Cms使用。
 *  CMS (Old) 老年代
 *      Concurrent mark sweep 并发回收、毛病较多
 *      2次stop-the-wold，第一次标识少的根节点。然后并发标记。stop-the-wold 标记新产生的。并发处理垃圾
 *      问题： Concurrent Model Failure  临时启用Serial Old收集器来重新进行老年代的垃圾收集（）
 *  G1  分而治之（分区）： 也是并发收集，优先扫描存活对象最的区域。 G1会发生FGC(默认使用mixedGc,fullgc使用serial(同cms)，所以尽量不要发生FGC)
 *      old（老年区） ，survivor(存活区)，region(存放大对象)，eden(新生对象)
 *      CSet = Collection Set 可回收的card table
 *      RSet = Remembered Set  记录了其他Reqion中的对象到本Region的引用，RSet的价值在于 使得垃圾收集器不需要扫描整个堆找到谁引用了当前分区中的对象只需要扫描RSet即可
 *      出现FGC： 1.阔内存 2.提高cpu性能，提高回收的效率 3. 降低MixedGC触发的阈值，让MixedGC提早发生(默认是45%)
 *      使用  XX:initiatinaHeapOccupacvPercent 默认45%，这个过程类似CMS
 *  ZGC Shenandoah
 *
 *  card table： 使用bitmap 实现
 *      由于做YGC时，需要扫描整个OLD区，效率非常低，所以VM设计了CardTable，如果一个CardTable,如果一个old区cardTable中有对象指向Y区，就将它设为dirty。下次扫描只扫为dirty
 *  三色
 *  对象指针
 *  堆内存逻辑分区
 *  · 新生代   YGC
 *      --eden 区
 *  · 老年代   FGC
 *
 *  eden -> s1 -> s2 -> old  转换的过程发生 yGC
 *
 *  栈上分配
 *      - 线程私有小对象、无逃逸、支持标量替换、无需调整
 *  线程本地分配TLB(Thread local Allocation Buffer)
 *      - 占用eden默认1%、多线程的时候不用竞争eden就可以申请空间，提高效率、小对象、无需调整
 *  老年代
 *      - 大对象
 *  eden
 *
 *
 *  线程创建对象： 默认先往栈上分配，如果大，则往堆里面仍，默认往eden区。YGC S1 -> S2 -> Old
 *
 *  对象何时进入老年代-- 最大15，markword 里面只有4位标志Gc次数
 *
 *调优文档，官方
 * https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
 *
 * @author: sun.xd
 * @date: 2021-10-22 10:00
 **/
public class T07_GC {

    class User{
        int id;
        String name;

        public User(int id, String name) {
            this.id = id;
            this.name = name;
        }
    }

    void alloc(int i){
        new User(i,"name"+i);
    }

    public static void main(String[] args) {
        T07_GC t = new T07_GC();
        long l = System.currentTimeMillis();
        for (int i = 0; i < 1000_0000L; i++) {
            t.alloc(i);
        }
        System.out.println(System.currentTimeMillis()-l);
    }


}
